import asyncio
import os
from aiohttp import web, web_request
from PIL import Image
import struct
from src.utils.logger import get_logger
from src.dto.ota_info import (
    OTARequestHeaders,
    OTAInfoResponse,
    MQTTConfig,
    ServerTime,
    Firmware,
)

logger = get_logger(__name__)
STATIC_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), "static")


async def handle_root(request: web_request.Request):
    """示例HTTP端点"""
    try:
        headers_focus = OTARequestHeaders(
            device_id=request.headers.get("Device-Id", ""),  # mac address
            client_id=request.headers.get("Client-Id", ""),
            content_type=request.headers.get("Content-Type", "application/json"),
        )
        logger.info(headers_focus)
        resp_body = OTAInfoResponse(
            mqtt=MQTTConfig(
                endpoint="192.168.2.1:1883",
                client_id=f"GID_test@@@{headers_focus.device_id.replace(':', '_').lower()}"
                f"@@@{headers_focus.client_id.lower()}",
                username="eyJpcCI6IjE4My4xNC4xMzUuMTU1In0=",
                password="3iAw+y4Xl+dUlLm7JzIq+HS9z1TVqqrJz6L+SJD9f4Y=",
                publish_topic="device-server",
                subscribe_topic=f"devices/p2p/{headers_focus.device_id}",
            ),
            server_time=ServerTime(),  # 使用当前时间戳和默认时区
            firmware=Firmware(version="1.7.2"),  # 指定固件版本
        ).to_bytes()
        return web.json_response(body=resp_body)
    except Exception as e:
        logger.error(f"Error handling request: {e}")
        body = str(e).encode()
        return web.json_response(status=500, body=body)


async def img2lvgl(request: web_request.Request) -> web.Response:
    """
    将静态资源图像转换为RGB565格式的字节数据发送, 格式和static/xxx.png一致
    路由: /lvgl/{image_name}?width=128&height=64
    返回: RGB565格式的二进制数据
    """
    try:
        # 获取图片名称
        image_name = request.match_info["image_name"]

        # 从URL参数获取尺寸，如果没有提供则使用默认值
        try:
            width = int(request.query.get("width", "128"))
            height = int(request.query.get("height", "64"))
        except ValueError:
            logger.warning("Invalid width or height parameter, using default values")
            width, height = 128, 64

        # 验证尺寸范围（避免过大的图片）
        if width <= 0 or height <= 0 or width > 1920 or height > 1080:
            logger.warning(f"Invalid dimensions: {width}x{height}, using default values")
            width, height = 128, 64

        # 构建静态文件路径
        image_path = os.path.join(STATIC_DIR, image_name)

        # 检查文件是否存在
        if not os.path.exists(image_path):
            logger.warning(f"Image not found: {image_path}")
            return web.Response(status=404, text="Image not found")

        # 打开并处理图像
        with Image.open(image_path) as img:
            # 转换为RGB模式（如果不是的话）
            if img.mode != "RGB":
                img = img.convert("RGB")
            img = img.resize((width, height))  # 根据URL参数调整大小

            # 获取图片尺寸
            width, height = img.size
            logger.info(f"Converting image {image_name} to RGB565 with dimensions {width}x{height}")

            # 转换为RGB565格式
            rgb565_data = bytearray()

            # 逐像素转换（后续优化转为静态库处理）
            for y in range(height):
                for x in range(width):
                    r, g, b = img.getpixel((x, y))  # u8

                    # 转换为RGB565格式
                    # R: 5位 (0-31), G: 6位 (0-63), B: 5位 (0-31)
                    r5 = (r >> 3) & 0x1F  # 取高5位(0b11111)
                    g6 = (g >> 2) & 0x3F  # 取高6位(0b111111)
                    b5 = (b >> 3) & 0x1F  # 取高5位(0b11111)

                    # 组合成16位RGB565值: RRRRRGGGGGGBBBBB
                    rgb565 = (r5 << 11) | (g6 << 5) | b5

                    # 按小端序存储(低字节在前)
                    rgb565_data.extend(struct.pack("<H", rgb565))

            logger.info(
                f"RGB565 conversion completed. Output size: {len(rgb565_data)} bytes, head: {' '.join(f'0x{b:02x}' for b in rgb565_data[:8])} ..."
            )
            # 返回二进制数据
            return web.Response(
                body=rgb565_data,
                headers={
                    "Content-Type": "application/octet-stream",
                    "Content-Length": str(len(rgb565_data)),
                },
            )

    except Exception as e:
        logger.error(
            f"Error converting image {request.match_info.get('image_name', 'unknown')} to RGB565: {e}"
        )
        return web.Response(status=500, text=f"Internal server error: {str(e)}")


async def init_app():
    """应用初始化"""
    app = web.Application()

    # 添加路由
    app.add_routes(
        [
            web.get("/", handle_root),
            web.post("/", handle_root),
            web.static("/static/", STATIC_DIR, name="static"),
            web.get("/lvgl/{image_name}", img2lvgl),
        ]
    )

    # 添加生命周期钩子
    # app.on_startup.append(start_background_tasks)
    # app.on_cleanup.append(cleanup_background_tasks)

    return app


async def start(port: int = 8888):
    """主入口"""
    app = await init_app()

    # 在启动服务器前创建后台任务
    runner = web.AppRunner(app)
    await runner.setup()

    # 等待后台初始化完成（可选）
    # await asyncio.sleep(1)  # 等待初始任务启动
    # 启动HTTP服务器
    site = web.TCPSite(runner, "0.0.0.0", port)
    await site.start()
    logger.info(f"Server started at http://0.0.0.0:{port}")
    await asyncio.Event().wait()
